# -*- coding: utf-8 -*-
"""
Created on Fri Oct 18 10:19:02 2024.

@author: James
"""
# Import statements
import os

import numpy as np
import scipy.constants as const
import matplotlib.pyplot as plt

from calculation_class import calculation

import matplotlib as mpl


# Constants
pi = np.pi
c = const.c  # [m/s] Speed of light
h = const.h  # [J/Hz] Plank constant
e_charge = const.elementary_charge  # [C] Electronic charge
k_B = const.k  # [J/K] Boltzman constant
hbar = const.hbar  # [Js] Reduced planks constant

# Plotting settings
mpl.rcParams.update(mpl.rcParamsDefault)
plt.rcParams["font.family"] = "Times New Roman"

data_folder = 'data/'
os.makedirs(data_folder, exist_ok=True)

fig_dict = {'dpi': 300,
            'line figsize': (4, 3),
            'contour figsize': (3, 3),
            'final contour figsize': (3,3),
            'label': (0.05, 0.95)}

cmap_dict = {'cmap': 'rainbow',
             'N_levels': 100,
             'max': 1e3,
             'min': 1e-1,
             'step': 2000,
             'levels': [0.1, 1, 10, 100, 1e3, 10e3, 20e3],
             'record_level': [0.0000001, 150, 10e3],
             'cmap_ticks': [1e-1, 1e0, 1e1, 1e2, 1e3],
             'cbar_pad': 0.2}


final_cmap_dict = {'cmap': cmap_dict['cmap'],
                   'N_levels': 100,
                   'max': 150,
                   'min': 5,
                   'step': 2000,
                   'levels': [1,4, 5, 7, 1e1, 15, 25, 50, 100],
                   'record_level': [0.0001, 15e1, 10e3],
                   'cmap_ticks': [10, 100]}

RIN_data = {'default': -100,
            'list': [-80, -100, -120],
            'limits': [-80, -120]}

Tm_data = {'default': 10*60,
           'list': [60, 600, 200 * 60],
           'limits': [60, 250 * 60]}

Pl_data = {'default': 10,
           'list': [1, 10, 100],
           'limits': [1, 100]}

w0_data = {'limits': [100e-6,  30e-2],
           'list': [100e-6, 1e-2]}

key_schenarios = ({'name': 'Benchmark',
                   'T_m': 10 * 60,
                   'P_laser': 10,
                   'RIN': -100},
                  {'name': 'Fast Future',
                   'T_m': 60,
                   'P_laser': 100,
                   'RIN': -120},
                  {'name': 'Currently Possible',
                   'T_m': 200 * 60,
                   'P_laser': 1,
                   'RIN': -80},
                  {'name': 'Best possible',
                   'T_m': 200 * 60,
                   'P_laser': 100,
                   'RIN': -100}
                  )



def test_beam_radius():# *
    """Create a graph that showing balancing variances to find the opt w0."""
    #  Set up default values
    RIN: float = RIN_data['default']
    power: float = Pl_data['default']
    Tm: float = Tm_data['default']
    complete_plot: bool = True
    # This determins if the sub sub sensitivity types are included on the graph
    w0_array = np.geomspace(*w0_data['limits'])
    w0_mm = w0_array * 1e3

    #  Setup blank data arrays
    sens_array = np.zeros(np.shape(w0_array))
    sens_IN_array = np.zeros(np.shape(w0_array))
    sens_PN_array = np.zeros(np.shape(w0_array))
    sens_SN_array = np.zeros(np.shape(w0_array))
    sens_DN_array = np.zeros(np.shape(w0_array))



    #  Iterate through all beam waist sizes and find the sensitivities.
    for arg, w0 in enumerate(w0_array):
        temp = calculation(w0=w0, RIN=RIN, P_laser=power, T_m=Tm)
        sens_array[arg] = temp.sensitivity
        sens_IN_array[arg] = temp.sensitivity_IN
        sens_PN_array[arg] = temp.sensitivity_PN
        sens_SN_array[arg] = temp.sensitivity_SN
        sens_DN_array[arg] = temp.sensitivity_DN

    temp = calculation(RIN=RIN, P_laser=power, T_m=Tm)
    w0_opt = temp.w0 * 1e3

    #  Scale up sensitivities to femto
    sens_array *= 1e15
    sens_IN_array *= 1e15
    sens_PN_array *= 1e15
    sens_SN_array *= 1e15
    sens_DN_array *= 1e15

    # Initiate graph
    fig, ax = plt.subplots(figsize=fig_dict['line figsize'],
                           dpi=fig_dict['dpi'])

    # Plot data
    ax.loglog(w0_mm, sens_array, label=r'$\mathcal{S}_{B}$')

    sub_sens_ls = '--'
    sub_sub_sens_ls = '-.'
    ax.loglog(w0_mm, sens_PN_array, ls=sub_sens_ls,
              label=r'$\mathcal{S}_{B,PN}$')
    ax.loglog(w0_mm, sens_SN_array, ls=sub_sens_ls,
              label=r'$\mathcal{S}_{B,SN}$')

    ax.loglog(w0_mm, sens_DN_array, ls=sub_sens_ls,
              label=r'$\mathcal{S}_{B,DN}$')

    ax.loglog(w0_mm, sens_IN_array, ls=sub_sens_ls,
              label=r'$\mathcal{S}_{B,RIN}$')
    ax.vlines(w0_opt, 1e-3, 2, color='k', label=r'Optimized $w_0$')

    # Plot formatting
    ax.set_xlim([0.1, 300])
    ax.set_ylim([1e-3, 2])

    sqrt_Hz = r'$\sqrt{\text{Hz}}$'  # Have to use this awkward method for formatting.
    ax.set_ylabel(f'Sensitivity (fT/{sqrt_Hz})')
    w0 = r'$w_0$'
    ax.set_xlabel(f'{w0} (mm)')


    # Add subfig label
    plt.figtext(*fig_dict['label'], 'a)', fontweight='bold')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()#which='both')
    ax.legend(loc='upper right')

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'beam-waist.png')
    plt.show()




def fundamental_contour_plot():# *
    """Create a contour plot showing how Plaser affects fund noise."""
    # Define defaults
    p_array = np.geomspace(*Pl_data['limits'])
    Tm_array = np.geomspace(*Tm_data['limits'])

    # Make independent variable meshes
    p_mesh, Tm_mesh = np.meshgrid(p_array, Tm_array)
    # Make empty array for fundamental sensitivities
    sens_FN_mesh = np.zeros(np.shape(p_mesh))

    # Populate the sensitivity mesh
    for arg_i, p_laser in enumerate(p_array):
        for arg_j, T_m in enumerate(Tm_array):
            temp = calculation(T_m=T_m, P_laser=p_laser)
            sens_FN_mesh[arg_j, arg_i] = temp.sensitivity_FN

    # Initiate plot
    fig, ax = plt.subplots(figsize=fig_dict['contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_xscale('log')
    ax.set_yscale('log')

    # Scale data
    sens_FN_mesh *= 1e18
    Tm_mesh /= 60

    # Plot color data
    color_contour = ax.contourf(p_mesh, Tm_mesh, sens_FN_mesh,
                                cmap=cmap_dict['cmap'],
                                levels=np.geomspace(cmap_dict['min'],
                                                    cmap_dict['max'],
                                                    cmap_dict['step']),
                                norm=mpl.colors.LogNorm())

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=cmap_dict['cmap_ticks'],
                        orientation='horizontal', pad=cmap_dict['cbar_pad'])
    cbar.set_label(r'Fundamental Sensitivity (aT/$\sqrt{\text{Hz}}$)', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(p_mesh, Tm_mesh, sens_FN_mesh,
                               levels=cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Add subfig label
    plt.figtext(*fig_dict['label'], '(a)', fontweight='bold')

    # Format plot

    ax.set_xlabel('Laser Power (W)')
    ax.set_ylabel('Measurement Time (min)')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'fundamental-dominated.png')
    plt.show()



def RIN_contour_plot():# *
    """Create a contour plot showing how Plaser affects fund noise."""
    # Define defaults
    RIN_array = np.geomspace(*RIN_data['limits'])
    p_laser = Pl_data['default']
    Tm_array = np.geomspace(*Tm_data['limits'])

    # Make independent variable meshes
    RIN_mesh, Tm_mesh = np.meshgrid(RIN_array, Tm_array)
    # Make empty array for fundamental sensitivities
    sens_IN_mesh = np.zeros(np.shape(RIN_mesh))

    # Populate the sensitivity mesh
    for arg_i, RIN in enumerate(RIN_array):
        for arg_j, T_m in enumerate(Tm_array):
            temp = calculation(RIN=RIN, T_m=T_m, P_laser=p_laser)
            sens_IN_mesh[arg_j, arg_i] = temp.sensitivity_IN

    # Initiate plot
    fig, ax = plt.subplots(figsize=fig_dict['contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_yscale('log')

    # Scale data
    sens_IN_mesh *= 1e18
    Tm_mesh /= 60

    # Plot color data
    color_contour = ax.contourf(RIN_mesh, Tm_mesh, sens_IN_mesh,
                                cmap=cmap_dict['cmap'],
                                levels=np.geomspace(cmap_dict['min'],
                                                    cmap_dict['max'],
                                                    cmap_dict['step']),
                                norm=mpl.colors.LogNorm())

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=cmap_dict['cmap_ticks'],
                        orientation='horizontal', pad=cmap_dict['cbar_pad'])
    cbar.set_label(r'Technical RIN Sensitivity (aT/$\sqrt{\text{Hz}}$)', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(RIN_mesh, Tm_mesh, sens_IN_mesh,
                               levels=cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)


    # Add subfig label
    plt.figtext(*fig_dict['label'], '(b)', fontweight='bold')

    # Format plot

    ax.set_xlabel('RIN (dBc/Hz)')
    ax.set_ylabel('Measurement Time (min)')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'RIN-dominated.png')
    plt.show()





def dominant_fundamental_contour_plot():# *
    """Create a contour plot while varying RIN and P_laser."""
    RIN_array = np.geomspace(*RIN_data['limits'])
    P_laser_array = np.geomspace(*Pl_data['limits'])
    Tm_array = np.geomspace(*Tm_data['limits'])

    Tm_mesh, P_laser_mesh = np.meshgrid(Tm_array, P_laser_array)
    sens_FN_mesh = np.zeros(np.shape(Tm_mesh))
    sens_PN_mesh = np.zeros(np.shape(Tm_mesh))
    sens_SN_mesh = np.zeros(np.shape(Tm_mesh))
    for arg_j, T_m in enumerate(Tm_array):
        for arg_i, P_laser in enumerate(P_laser_array):
            temp = calculation(T_m=T_m, P_laser=P_laser)
            sens_FN_mesh[arg_j, arg_i] = temp.sensitivity_FN * 1e18
            sens_PN_mesh[arg_j, arg_i] = temp.sensitivity_PN * 1e18
            sens_SN_mesh[arg_j, arg_i] = temp.sensitivity_SN * 1e18

    sens_ratio = (-sens_PN_mesh + sens_SN_mesh)/np.sqrt (sens_PN_mesh**2 + sens_SN_mesh**2)


    fig, ax = plt.subplots(figsize=fig_dict['contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_yscale('log')
    ax.set_xscale('log')
    color_contour = ax.contourf(Tm_mesh, P_laser_mesh, sens_ratio,
                                cmap='coolwarm',
                                levels=np.linspace(np.min(sens_ratio),
                                                   np.max(sens_ratio),
                                                    final_cmap_dict['step']))

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=[],
                        orientation='horizontal', pad=cmap_dict['cbar_pad'])
    cbar.set_label(r'Dominant Noise Source', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(Tm_mesh, P_laser_mesh, sens_FN_mesh,
                               levels=final_cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    black_contour = ax.contour(Tm_mesh, P_laser_mesh, sens_FN_mesh,
                               levels=final_cmap_dict['record_level'],
                               colors='black', linestyles='--')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    # black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
    #                            levels=final_cmap_dict['record_level'],
    #                            colors='black', linestyles='--')

    # Format plot

    ax.set_ylabel('Laser Power (W)')
    ax.set_xlabel('Measurement time (min))')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()


    # Add colorbar label
    x_location = 0.15
    plt.figtext(0.95, x_location, "Shot")
    plt.figtext(-0.1, x_location, "Projection")

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'fundamental-ratio-plot.png')
    plt.show()



def detector_contour_plot():# *
    """Create a contour plot showing how Plaser affects detector noise."""
    # Define defaults
    RIN = RIN_data['default']
    p_array = np.geomspace(*Pl_data['limits'])
    Tm_array = np.geomspace(*Tm_data['limits'])

    # Make independent variable meshes
    p_mesh, Tm_mesh = np.meshgrid(p_array, Tm_array)
    # Make empty array for fundamental sensitivities
    sens_DN_mesh = np.zeros(np.shape(p_mesh))

    # Populate the sensitivity mesh
    for arg_i, p_laser in enumerate(p_array):
        for arg_j, T_m in enumerate(Tm_array):
            temp = calculation(RIN=RIN, T_m=T_m, P_laser=p_laser)
            sens_DN_mesh[arg_j, arg_i] = temp.sensitivity_DN

    # Initiate plot
    fig, ax = plt.subplots(figsize=fig_dict['contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_xscale('log')
    ax.set_yscale('log')

    # Scale data
    sens_DN_mesh *= 1e18
    Tm_mesh /= 60

    # Plot color data
    color_contour = ax.contourf(p_mesh, Tm_mesh, sens_DN_mesh,
                                cmap=cmap_dict['cmap'],
                                levels=np.geomspace(cmap_dict['min'],
                                                    cmap_dict['max'],
                                                    cmap_dict['step']),
                                norm=mpl.colors.LogNorm())

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=cmap_dict['cmap_ticks'],
                        orientation='horizontal', pad=cmap_dict['cbar_pad'])
    cbar.set_label(r'Detector Sensitivity (aT/$\sqrt{\text{Hz}}$)', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(p_mesh, Tm_mesh, sens_DN_mesh,
                               levels=cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Add subfig label
    plt.figtext(*fig_dict['label'], '(c)', fontweight='bold')

    # Format plot

    ax.set_xlabel('Laser Power (W)')
    ax.set_ylabel('Measurement Time (min)')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'detector-dominated.png')
    plt.show()







def total_contour_plot():# *
    """Create a contour plot while varying RIN and P_laser."""
    RIN_array = np.geomspace(*RIN_data['limits'])
    P_laser_array = np.geomspace(*Pl_data['limits'])
    T_m = Tm_data['default']

    RIN_mesh, P_laser_mesh = np.meshgrid(RIN_array, P_laser_array)
    sens_mesh = np.zeros(np.shape(RIN_mesh))

    sens_FN_mesh = np.zeros(np.shape(RIN_mesh))
    sens_TN_mesh = np.zeros(np.shape(RIN_mesh))
    sens_DN_mesh = np.zeros(np.shape(RIN_mesh))
    for arg_i, RIN in enumerate(RIN_array):
        for arg_j, P_laser in enumerate(P_laser_array):
            temp = calculation(T_m=T_m, RIN=RIN, P_laser=P_laser)
            sens_mesh[arg_j, arg_i] = temp.sensitivity * 1e18
            sens_FN_mesh[arg_j, arg_i] = temp.sensitivity_FN * 1e18
            sens_TN_mesh[arg_j, arg_i] = temp.sensitivity_IN * 1e18
            sens_DN_mesh[arg_j, arg_i] = temp.sensitivity_DN * 1e18

   # sens_mesh = np.sqrt(sens_TN_mesh ** 2 + sens_FN_mesh ** 2)
    fig, ax = plt.subplots(figsize=fig_dict['final contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_yscale('log')
    color_contour = ax.contourf(RIN_mesh, P_laser_mesh, sens_mesh,
                                cmap=final_cmap_dict['cmap'],
                                levels=np.geomspace(final_cmap_dict['min'],
                                                    final_cmap_dict['max'],
                                                    final_cmap_dict['step']),
                                norm=mpl.colors.LogNorm())

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=final_cmap_dict['cmap_ticks'],
                        orientation='horizontal', pad=cmap_dict['cbar_pad'])
    cbar.set_label(r'Sensitivity (aT/$\sqrt{\text{Hz}}$)', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
                               levels=final_cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
                               levels=final_cmap_dict['record_level'],
                               colors='black', linestyles='--')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    # black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
    #                            levels=final_cmap_dict['record_level'],
    #                            colors='black', linestyles='--')

    # Format plot

    ax.set_ylabel('Laser Power (W)')
    ax.set_xlabel('RIN (dBc/Hz)')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()


    # Add colorbar label
    x_location = 0.23
    plt.figtext(0.92, x_location, f"{final_cmap_dict['max']:.0f}")
    plt.figtext(0.15, x_location, f"{final_cmap_dict['min']:.0f}")

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'final-plot.png')
    plt.show()




def dominant_total_contour_plot():# *
    """Create a contour plot while varying RIN and P_laser."""
    RIN_array = np.geomspace(*RIN_data['limits'])
    P_laser_array = np.geomspace(*Pl_data['limits'])
    T_m = Tm_data['default']

    RIN_mesh, P_laser_mesh = np.meshgrid(RIN_array, P_laser_array)
    sens_mesh = np.zeros(np.shape(RIN_mesh))
    sens_FN_mesh = np.zeros(np.shape(RIN_mesh))
    sens_TN_mesh = np.zeros(np.shape(RIN_mesh))
    sens_DN_mesh = np.zeros(np.shape(RIN_mesh))
    for arg_i, RIN in enumerate(RIN_array):
        for arg_j, P_laser in enumerate(P_laser_array):
            temp = calculation(T_m=T_m, RIN=RIN, P_laser=P_laser)
            sens_mesh[arg_j, arg_i] = temp.sensitivity * 1e18
            sens_FN_mesh[arg_j, arg_i] = temp.sensitivity_FN * 1e18
            sens_TN_mesh[arg_j, arg_i] = temp.sensitivity_IN * 1e18
            sens_DN_mesh[arg_j, arg_i] = temp.sensitivity_DN * 1e18

   # sens_TN_mesh = np.sqrt(sens_TN_mesh ** 2 + sens_DN_mesh ** 2)
    sens_ratio = (sens_TN_mesh - sens_FN_mesh)/np.sqrt((sens_FN_mesh**2 + sens_TN_mesh**2))
    #sens_mesh = np.sqrt(sens_TN_mesh ** 2 + sens_FN_mesh ** 2)


    fig, ax = plt.subplots(figsize=fig_dict['final contour figsize'],
                           dpi=fig_dict['dpi'])

    ax.set_yscale('log')
    color_contour = ax.contourf(RIN_mesh, P_laser_mesh, sens_ratio,
                                cmap='coolwarm',
                                levels=np.linspace(-1,
                                                    1,
                                                    final_cmap_dict['step']))

    # Create and format colorbar
    cbar = fig.colorbar(color_contour, ax=ax, ticks=[],
                        orientation='horizontal', pad=0.2)
    cbar.set_label(r'Dominant Noise Source', rotation=0)

    # Plot black log refernces
    black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
                               levels=final_cmap_dict['levels'],
                               colors='black')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
                               levels=final_cmap_dict['record_level'],
                               colors='black', linestyles='--')
    # Label black lines on contour plot
    plt.clabel(black_contour, inline=1, fmt=r'%1.0f', fontsize=8)

    # Plot black record refernces
    # black_contour = ax.contour(RIN_mesh, P_laser_mesh, sens_mesh,
    #                            levels=final_cmap_dict['record_level'],
    #                            colors='black', linestyles='--')

    # Format plot

    ax.set_ylabel('Laser Power (W)')
    ax.set_xlabel('RIN (dBc/Hz)')

    ax.tick_params(axis='x', which='both', direction='in')
    ax.tick_params(axis='y', which='both', direction='in')

    ax.grid()


    # Add colorbar label
    x_location = 0.085
    #plt.figtext(0.94, x_location+0.07, "RIN", rotation=90)
    #plt.figtext(0.14, x_location+0.06, "Fund.", rotation=90)
    plt.figtext(0.92, x_location+0.07, r"$\mathcal{S}_{B,RIN}$")
    plt.figtext(0.07, x_location+0.07,r"$\mathcal{S}_{B,FN}$")

    # Plot saving
    plt.tight_layout()
    plt.savefig(data_folder + 'final-ratio-plot.png', bbox_inches='tight', pad_inches=0.05)
    plt.show()




def main():
    """Run code to generate graphs and tables."""


    test_beam_radius()  # Figure 2

    fundamental_contour_plot()  # Figure 3 a)
    RIN_contour_plot()   # Figure 3 b)
    detector_contour_plot()  # Figure 3 c)
    total_contour_plot()  # Figure 4
    dominant_total_contour_plot()  # Figure 5





if __name__ == '__main__':
    main()
